package com.general.seckill.stockservice;

import com.alibaba.fastjson.JSON;
import com.general.seckill.common.Result;
import com.general.seckill.stockservice.entity.Product;
import com.general.seckill.stockservice.entity.ProductExample;
import com.general.seckill.stockservice.feign.OrderServiceFeign;
import com.general.seckill.stockservice.mapper.ProductMapper;
import com.general.seckill.stockservice.request.StockDecreaseDTO;
import com.general.seckill.stockservice.rocketmq.SecKillEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @description: StockService
 * @author: general
 * @version: 1.0
 * @create: 2022-04-30 21:23
 **/
@Service
@Slf4j
public class StockService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ProductMapper productMapper;

    @Resource
    private OrderServiceFeign orderServiceFeign;

    private static final String STOCK_PREFIX = "stock:product:%s";

    private static final String LUA_SCRIPT = "if tonumber(redis.call('get',KEYS[1]))>=tonumber(ARGV[1]) then return " +
            "redis.call('decrby',KEYS[1],ARGV[1]) else return -1 end";


    public Map<String, Object> decreaseStock(StockDecreaseDTO decreaseDTO) {
        String cacheKey = String.format(STOCK_PREFIX, decreaseDTO.getProductId());
        String count = stringRedisTemplate.opsForValue().get(cacheKey);
        if(StringUtils.isEmpty(count)){
            // 先查缓存 缓存没有查询数据库 写入缓存
            ProductExample example = new ProductExample();
            example.createCriteria().andIdEqualTo(decreaseDTO.getProductId()).andDeletedEqualTo(0);
            List<Product> products = productMapper.selectByExample(example);
            if(CollectionUtils.isNotEmpty(products)){
                Product product = products.get(0);
                stringRedisTemplate.opsForValue().set(cacheKey, product.getStock().toString());
            }
            else{
                stringRedisTemplate.opsForValue().set(cacheKey, "0");
            }
        }
        // 扣库存成功 创建订单
        Object result = stringRedisTemplate.execute(
                (RedisConnection connection) -> connection.eval(
                        LUA_SCRIPT.getBytes(),
                        ReturnType.INTEGER,
                        1,
                        cacheKey.getBytes(),//商品id
                        "1".getBytes()));//这块的需求数量可以修改为其他值
        System.out.println(result);
        if(Objects.nonNull(result)){
            if(result.toString().equals("-1")){
                log.warn("params:{} 秒杀失败!", JSON.toJSONString(decreaseDTO));
            }else {
                SecKillEntity entity = new SecKillEntity();
                entity.setUserId(decreaseDTO.getUserId());
                entity.setProductId(decreaseDTO.getProductId());
                Result<String> orderResult = orderServiceFeign.createOrder(entity);
                if(200 == orderResult.getCode()){
                    log.info("秒杀成功，生成订单成功");
                }
                else{
                    // todo 库存待回滚
                    log.error("秒杀成功，生成订单失败");
                }
            }
        }
        return null;
    }
}
